package com.eight.vote.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.eight.vote.pojo.*;
import com.eight.vote.mapper.VMessageMapper;
import com.eight.vote.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.eight.vote.util.*;
import com.eight.vote.vo.VoteVo;
import com.eight.vote.vo.GetVoteVo;
import com.eight.vote.vo.IndexVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 点点星言
 * @since 2022-10-16
 */
@Service
@Slf4j
public class VMessageServiceImpl extends ServiceImpl<VMessageMapper, VMessage> implements VMessageService {

    @Autowired
    VUserService userService;

    @Autowired
    VOptionService optionService;

    @Autowired
    CategoryService categoryService;

    @Autowired
    VOptionInfoService optionInfoService;

    @Override
    public Result getHotVote(Integer pageNum,Integer pageSize) {
        //查询浏览量大于常量的投票信息
        QueryWrapper<VMessage> wrapper = new QueryWrapper<>();
        wrapper.orderByDesc("views");
        List<VMessage> messageList = baseMapper.selectList(wrapper);
        log.debug("投票信息集合：{}",messageList.toString());
        //通过对应的投票信息中的userid查询对应的昵称
        List<Long> userId = messageList.stream().map((item) -> {
            return item.getUserId();
        }).collect(Collectors.toList());
        List<VUser> userList = userId.stream().map((item) -> {
            return userService.getById(item);
        }).collect(Collectors.toList());
        //将昵称和投票信息中对应的字段封装进indexVo中
        List<IndexVo> IndexVos = userList.stream().map(item -> {
            IndexVo indexVo = new IndexVo();
            indexVo.setName(item.getName());
            indexVo.setUserId(item.getUserId());
            return indexVo;
        }).collect(Collectors.toList());
        for (IndexVo index: IndexVos) {
            for (VMessage message:messageList) {
                if (index.getUserId()==message.getUserId()&&message.getMsgId()!=null) {
                    index.setTitle(message.getTitle());
                    index.setCreateTime(message.getCreateTime());
                    index.setViews(message.getViews());
                    index.setMsgId(message.getMsgId());
                    index.setCategoryId(message.getCategoryId());
                    index.setPermissionType(message.getPermissionType());
                    message.setMsgId(null);
                    break;
                }
            }
        }
        log.debug(IndexVos.toString());
        //检索mysql中的类型表，根据类型id查询出类型名称
        IndexVos.stream().forEach(item->{
            Long categoryId = item.getCategoryId();
            Category category = categoryService.getById(categoryId);
            item.setCategoryName(category.getCategoryName());
        });
        //对indexVos进行分页
        Page pages = ListPage.getPages(pageNum, pageSize, IndexVos);
        //将indexVo返回
        return Result.ok(pages);
    }

    @Override
    @Transactional
    public Result addVote(VoteVo voteVo) {
        log.debug("前端传入的投票信息：{}", voteVo.toString());
        //从请求头中获取token
        Long userId = UserHolder.getUserId();
        //创建投票信息对象
        VMessage message = new VMessage();
        //将数据从前端传入的vo copy到投票信息对象中
         BeanUtils.copyProperties(voteVo,message);
         message.setCreateTime(LocalDateTime.now());
         message.setUserId(userId);
         message.setViews(Constant.VIEWS_INIT);
        LocalDateTime localDateTime = TimeUtil.toLocalDateTime(voteVo.getEndTime(), Constant.DATE_FORMATTER);
        message.setEndTime(localDateTime);
        //权限优化，但是先不管
//        if (message.getLockPwd()==null&&message.getPermissionType()==3) {
//            return Result.fail("权限为密码制，但是没有传入密码，请重新确认");
//        }
        //分别调用不同的Service将对应的数据添加到mysql
        baseMapper.insert(message);
        voteVo.getOptions().stream().forEach((item)->{
            item.setInfoId(message.getMsgId());
            optionService.save(item);
        });
        //返回ok
        return Result.ok();
    }

    @Override
    public Result userAddVote(VOption option) {
        //获取选项值
        String optionValue = option.getOptionValue();
        //判断选项表中是否已经存在该选项，
        QueryWrapper<VOption> wrapper = new QueryWrapper<>();
        wrapper.eq("o_value",optionValue);
        VOption vOption = optionService.getOne(wrapper);
        if (vOption!=null) {
            //存在，返回异常
            return Result.fail("该选项已存在！");
        }
        //不存在，填表入库
        optionService.save(option);
        //返回正确信息
        return Result.ok();
    }

    @Override
    public Result searchVote(String keyword,Integer pageNum,Integer pageSize) {
        log.debug("keyword:{}",keyword);
        //构造查询条件
        QueryWrapper<VMessage> wrapper = new QueryWrapper<>();
        wrapper.like("title",keyword);
//        构建分页对象
        Page<VMessage> objectPage = new Page<>(pageNum, pageSize);

//        调用分页方法查询
        Page<VMessage> page = page(objectPage, wrapper);
                log.debug("投票信息:{}",page.toString());
//        返回数据
        return Result.ok(page);
    }

    @Override
    @Transactional
    public Result getVoteById(GetVoteVo getVoteVo) {
        //获取vo中的各项参数
        Long msgId = getVoteVo.getMsgId();
        Integer permissionType = getVoteVo.getPermissionType();
        String lockPwd = getVoteVo.getLockPwd();
        VoteVo voteFromDB = null;
        //判断权限类型是否为3
        if (permissionType!=3) {
            //如果不为3，调用对应的方法并返回数据即可
            voteFromDB = getVoteFromDB(msgId,permissionType);
            if (voteFromDB==null)
                return Result.fail("权限类型不一致，别想乱搞嗷");
            return Result.ok(voteFromDB);
        }
        //如果为3，则同样根据id查询数据，并对比密码是否相同
        VMessage message = baseMapper.selectById(msgId);
        String lockPwdFromDB = message.getLockPwd();
        if (!lockPwdFromDB.equals(lockPwd)) {
            //如果不相同，直接报投票信息密码错误异常
            return Result.fail("密码错误，请确实是否为正确密码");
        }
        //浏览量+1
        addViews(message);
        //如果相同，则调用对应方法并返回数据即可
        voteFromDB = getVoteFromDB(msgId,permissionType);
        if (voteFromDB==null)
            return Result.fail("权限类型不一致，别想乱搞嗷");
        return Result.ok(voteFromDB);
    }

    @Override
    public Result getVoteByUserId(Integer pageNum,Integer pageSize) {
        //获取userid
        Long userId = UserHolder.getUserId();
        //构建分页对象
        Page<VMessage> page = new Page<>(pageNum, pageSize);
        //构建查询对象
        QueryWrapper<VMessage> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id",userId);
        //调用对应的方法进行查询
        Page<VMessage> messagePage =baseMapper.selectPage(page,wrapper);
        //返回数据
        return Result.ok(messagePage);
    }

    @Override
    @Transactional
    public Result deleteMessage(Long msgId) {
        //获取用户id
        Long userId = UserHolder.getUserId();
        //通过msgId从数据库中获取message对象
        VMessage message = baseMapper.selectById(msgId);
        //将数据库中的userId与当前获取的userId进行对比
        if (userId!= message.getUserId()) {
            //不相同，报不能删除其他用户异常
            return Result.fail("不能删除其他用户的投票信息！");
        }
        //相同，构建删除选项对象
        QueryWrapper<VOption> optionQueryWrapper = new QueryWrapper<>();
        optionQueryWrapper.eq("i_id",msgId);
        //调用对应的方法查询对象，
        List<VOption> options =  optionService.getByWrapperList(optionQueryWrapper);
        //并删除对应的记录
        optionService.remove(optionQueryWrapper);
        //获取所有option的主键id
        List<Long> oIdList = options.stream().map(item -> item.getOId()).collect(Collectors.toList());
        //构建删除投票记录表对象
        oIdList.stream().forEach(item->{
            QueryWrapper<VOptionInfo> wrapper = new QueryWrapper<>();
            wrapper.eq("o_id",item);
            optionInfoService.remove(wrapper);
        });
        baseMapper.deleteById(msgId);
        return Result.ok();
    }

    private VoteVo getVoteFromDB(Long msgId,Integer permissionType){
        //获取userId用于判断是否为当前用户所投的票
        Long userId = UserHolder.getUserId();
        //通过id查询投票信息
        VMessage message = baseMapper.selectById(msgId);
        if (message.getPermissionType()!=permissionType) {
            return null;
        }
        //构建选项查询条件
        QueryWrapper<VOption> wrapper = new QueryWrapper<>();
        wrapper.eq("i_id",msgId);
        //查询所有该投票信息对应的选项
        List<VOption> list = optionService.list(wrapper);
        //查询投票记录表，查询每个选项对应的投票结果
        //获取所有投票信息的投票结果
        list.stream().forEach(item->{
            QueryWrapper<VOptionInfo> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("o_id",item.getOId());
            Integer count = (int)optionInfoService.count(queryWrapper);
            item.setCount(count);
            queryWrapper.eq("u_id",userId);
            VOptionInfo one = optionInfoService.getOne(queryWrapper);
            if (one != null) {
                item.setIsUserFrom(1);
            }else {
                item.setIsUserFrom(0);
            }
        });
        //构建数据传输vo
        VoteVo voteVo = new VoteVo();
        //将数据封装进数据传输vo中
        voteVo.setOptions(list);
        BeanUtils.copyProperties(message,voteVo);
        //浏览量+1
        addViews(message);
        //返回数据
        return voteVo;
    }

    /**
     * 浏览量加1方法
     * @param message
     */
    private void addViews(VMessage message){
        Integer views = message.getViews();
        views = views+1;
        message.setViews(views);
        baseMapper.updateById(message);
    }




}
